#ifndef __INCLUDED_CBL_RESOURCEPTR_H__
#error "CBL_ResourcePtr.hpp must not be used directly. Use CBL_ResourcePtr.h instead."
#else
#ifndef __INCLUDED_CBL_RESOURCEPTR_HPP__
#define __INCLUDED_CBL_RESOURCEPTR_HPP__

// -------------------------------------------------------------------------------------

CB_FORCEINLINE bool CB_INLINE_ATTR IResource::ReleaseReference() 
{ 
	--m_ReferenceCounter;
    Debug::Assert(m_ReferenceCounter >= 0, "IResource::ReleaseHandle called at least twice on the last instance.");
    return m_ReferenceCounter <= 0; 
}

// -------------------------------------------------------------------------------------

template <typename TType>
CResourcePtr<TType>::CResourcePtr()
	: m_pObject(NULL)
{
}

// -------------------------------------------------------------------------------------

template <typename TType>
CResourcePtr<TType>::CResourcePtr(IResource* _pObject)
	: m_pObject(static_cast<TType*>(_pObject))
{
    if (m_pObject)
    	m_pObject->KeepReference();
}

// -------------------------------------------------------------------------------------

template <typename TType>
CResourcePtr<TType>::CResourcePtr(const CResourcePtr<TType>& _rCopy)
: m_pObject(static_cast<TType*>(_rCopy.GetObject()))
{
	if (m_pObject)
    	m_pObject->KeepReference();
}

// -------------------------------------------------------------------------------------

template <typename TType>
template <typename TType2>
CResourcePtr<TType>::CResourcePtr(const CResourcePtr<TType2>& _rCopy)
	: m_pObject(static_cast<TType*>(_rCopy.GetObject()))
{
	if (m_pObject)
    	m_pObject->KeepReference();
}

// -------------------------------------------------------------------------------------

template <typename TType>
CResourcePtr<TType>::~CResourcePtr()
{
    Release();
}

// -------------------------------------------------------------------------------------

template <typename TType>
CB_FORCEINLINE CResourcePtr<TType>& CB_INLINE_ATTR CResourcePtr<TType>::operator = (IResource* _pNewObject)
{
    Release();
    
    m_pObject = static_cast<TType*>(_pNewObject);
    
    if (m_pObject)
    	m_pObject->KeepReference();
    
    return *this;
}

// -------------------------------------------------------------------------------------

template <typename TType>
CB_FORCEINLINE CResourcePtr<TType>& CB_INLINE_ATTR CResourcePtr<TType>::operator = (const CResourcePtr<TType>& _rCopy)
{
    return (*this = _rCopy.GetObject());
}

// -------------------------------------------------------------------------------------

template <typename TType>
template <typename TType2>
CB_FORCEINLINE CResourcePtr<TType>& CB_INLINE_ATTR CResourcePtr<TType>::operator = (const CResourcePtr<TType2>& _rCopy)
{
    return (*this = _rCopy.GetObject());
}

// -------------------------------------------------------------------------------------

template <typename TType>
CB_FORCEINLINE void CB_INLINE_ATTR CResourcePtr<TType>::Release()
{
    if (m_pObject)
    {
        if (m_pObject->ReleaseReference())
        	delete m_pObject;
        
        m_pObject = NULL;
    }
}

// -------------------------------------------------------------------------------------

template <typename TType>
CB_FORCEINLINE TType* CB_INLINE_ATTR CResourcePtr<TType>::Retain()
{
    TType* pObject = GetObject();
    
    if (m_pObject)
    {
    	m_pObject->ReleaseReference();
        m_pObject = NULL;
    }
    
    return pObject;
}

#endif
#endif